package com.lcm.learn.lcmcode.proxy.cglib;

import org.springframework.cglib.core.DebuggingClassWriter;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;


/**
 * @description:
 * @author: lcm
 * @create: 2020-01-19 09:16
 **/

public class SimpleCGLibDemo {

    private static <T> T getProxy(Class<T> cls) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(cls);
       // enhancer.setCallbackFilter(cls);
        enhancer.setCallback(new SimpleInterceptor());
        return (T) enhancer.create();
    }

    public static void main(String[] args) throws InterruptedException {
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "C:\\Users\\mcmc\\Desktop\\spring cloud\\spring-cloud-alibaba-master\\spring-cloud-alibaba-examples\\rocketmq-example\\lcm-code\\com\\lcm\\learn\\lcmcode\\proxy\\cglib");
        RealService proxyService = getProxy(RealService.class);
        proxyService.sayHello(new ArrayList<>());

        Father father=proxyService;
        father.sayHello(new ArrayList<>());
    }

}

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface Test{}


abstract class Father<T>{

    public abstract T sayHello(T t) ;

}

class RealService extends Father<List> {

    public List sayHello() {
        return this.sayHello(new ArrayList());
    }

    @Test
    @Override
    public List sayHello(List list) {
        System.out.println("hello");
        return list;
    }

}

class SimpleInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object object, Method method,
                            Object[] args, MethodProxy proxy) throws Throwable {
        if(!method.isAnnotationPresent(Test.class))
          return  proxy.invokeSuper(object, args);

        System.out.println("entering " + method.getName());
        Object result = proxy.invokeSuper(object, args);
        System.out.println("leaving " + method.getName());
        return result;
    }
}